package com.djinquan.common.aspect;

import com.djinquan.common.facade.RedissonLock;
import com.djinquan.common.service.RedissonService;
import com.djinquan.common.util.FunUtil;
import com.djinquan.common.util.SpelUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.UUID;
import java.util.function.Supplier;

/**
 * @Desc:
 * @Group:美的集团-营销系统-技术组
 * @Author dengjq15
 * @Date 2023/8/6
 */
@Aspect
@Component
@Order(0)
public class RedissonLockAspect {

    @Autowired
    private RedissonService redissonService;

    private static final String elKeyStr = "lock";

    @Around("@annotation(com.djinquan.common.facade.RedissonLock)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("aaaaaaa");
        //这个AOP拦截的是ServiceImpl的一个方法，然后这个ServiceImpl又启动了事务管理，而事务管理又是基于AOP的。
        //也就是说，这个权限的@Around的切面拦截的是个代理对象的方法，而代理对象的方法是不会把原来父类中的方法的注解加上去的，所以这里这个注解的对象为null。
        Method method = ((MethodSignature)joinPoint.getSignature()).getMethod();

        RedissonLock redissonLock = method.getAnnotation(RedissonLock.class);
        if(FunUtil.objIsNull(redissonLock)){
            method = joinPoint.getTarget().getClass().getDeclaredMethod(joinPoint.getSignature().getName(),method.getParameterTypes());
            redissonLock = method.getAnnotation(RedissonLock.class);
        }
        //默认方法限定名称+注释排名(可选多个)
        String prefix = FunUtil.objIsNull(redissonLock.prefixKey())? SpelUtil.generateKeyBySpEL(elKeyStr,method,joinPoint.getArgs()):redissonLock.prefixKey();
        String key = prefix+":"+SpelUtil.generateKeyBySpEL(redissonLock.key(),method,joinPoint.getArgs());
        return redissonService.executeWithLockThrows(key,redissonLock.waitTime(),redissonLock.leaseTime(),
                redissonLock.unit(),joinPoint);
    }
}
